package tournoi.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import tournoi.modele.Arbitre;
import tournoi.modele.Colonne;
import tournoi.modele.Colonne.EtatColonne;
import tournoi.modele.Equipe;
import tournoi.modele.Rencontre;
import tournoi.modele.Tournoi;
import tournoi.modele.Tournoi.EtatTournoi;
import tournoi.stateless.Gestion;

/**
 * Servlet implementation class AdminServlet
 */
@WebServlet("/admin")
public class AdminServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public AdminServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String action = request.getParameter("action");
		HttpSession session = request.getSession(true);
		String admin = (String) session.getAttribute("admin");

		Gestion facade = (Gestion) session.getAttribute("mafacade");

		if (facade == null) {
			Context ctx;
			try {
				ctx = new InitialContext();
				facade = (Gestion) ctx
						.lookup("java:global/TournoiWeb/GestionBean!tournoi.stateless.GestionLocal");
			} catch (NamingException e) {
				e.printStackTrace();
			}
			session.setAttribute("mafacade", facade);
		}

		/*
		 * =================================================================
		 * 
		 * TEST LOGIN
		 * 
		 * =================================================================
		 */
		if (action != null && action.equals("login")) {
			// Login de l'admin
			String login = request.getParameter("login");
			String pwd = request.getParameter("password");
			if (facade.authentifier(login, pwd)) {
				session.setAttribute("admin", login);
				session.removeAttribute("errorlogin");
				request.getRequestDispatcher("/admin/menu.jsp").forward(
						request, response);
			} else {
				session.setAttribute("errorlogin", true);
				request.getRequestDispatcher("/admin/login.jsp").forward(
						request, response);
			}

		} else if (admin == null) {
			// Si l'admin n'est pas authentifié
			request.getRequestDispatcher("/admin/login.jsp").forward(request,
					response);

		} else {
			/*
			 * =================================================================
			 * 
			 * LOGIN EFFECTUE
			 * 
			 * =================================================================
			 */
			if (action == null || action.equals("menu")) {

				// Action par défaut => menu admin
				request.getRequestDispatcher("/admin/menu.jsp").forward(
						request, response);

			}
			/*
			 * =================================================================
			 * 
			 * DIFFENTS MENUS
			 * 
			 * =================================================================
			 */
			else if (action.equals("menuEquipe")) {
				ArrayList<Equipe> equipes = (ArrayList<Equipe>) facade
						.recupererEquipes();

				request.setAttribute("equipes", equipes);
				request.getRequestDispatcher("/admin/menuEquipe.jsp").forward(
						request, response);

			} else if (action.equals("menuTournoi")) {
				ArrayList<Tournoi> tournois = (ArrayList<Tournoi>) facade
						.recupererTournois();

				request.setAttribute("tournois", tournois);
				request.getRequestDispatcher("/admin/menuTournoi.jsp").forward(
						request, response);

			} else if (action.equals("menuArbitre")) {
				ArrayList<Arbitre> arbitres = (ArrayList<Arbitre>) facade
						.recupererArbitres();

				request.setAttribute("arbitres", arbitres);
				request.getRequestDispatcher("/admin/menuArbitre.jsp").forward(
						request, response);
			}
			/*
			 * =================================================================
			 * 
			 * LES ACTIONS
			 * 
			 * =================================================================
			 */
			else if (action.equals("deconnexion")) {
				session.removeAttribute("admin");
				request.getRequestDispatcher("/admin/login.jsp").forward(
						request, response);
			} else if (action.equals("populate")) {
				/* ajouter le jeu de test */
				if (facade.recupererEquipes().size() == 0) {
					facade.populate();
					request.setAttribute("etat",
							"<div class='alert alert-success'><p>Jeu de données créé !</p></div>");
				}
				request.getRequestDispatcher("/admin/menu.jsp").forward(
						request, response);
			}
			/*
			 * =================================
			 * 
			 * TOURNOI
			 * 
			 * =================================
			 */
			/**
			 * ajoutTournoi(nomTournoi)
			 */
			else if (action.equals("ajoutTournoi")) {
				String nom = request.getParameter("nomTournoi");
				Tournoi t = new Tournoi(nom);
				/* si l'ajout est correct */
				if (nom != null && !nom.isEmpty() && facade.creerTournoi(t)) {
					List<Equipe> le = (ArrayList<Equipe>) facade
							.recupererEquipes();
					request.setAttribute("equipes", le);
					request.setAttribute("tournoi", t);
					request.getRequestDispatcher("/admin/equipeTournoi.jsp")
							.forward(request, response);
				} else {
					ArrayList<Tournoi> tournois = (ArrayList<Tournoi>) facade
							.recupererTournois();
					request.setAttribute("tournois", tournois);
					request.setAttribute("etat",
							"<div class='alert alert-success'><p>Erreur ajout</p></div>");
					request.getRequestDispatcher("/admin/menuTournoi.jsp")
							.forward(request, response);
				}
			}
			/**
			 * supprimerTournoi(id)
			 */
			else if (action.equals("supprimerTournoi")) {
				int numero = Integer.parseInt(request.getParameter("id"));
				/* On supprime le tournoi */
				facade.supprimerTournoi(numero);
				request.setAttribute("etat",
						"<div class='alert alert-warning'><p>Suppression effectuée !</p></div>");

				/* récupération des tournois pour l'affichage */
				ArrayList<Tournoi> tournois = (ArrayList<Tournoi>) facade
						.recupererTournois();
				/* On retourne sur le menu */
				request.setAttribute("tournois", tournois);
				request.getRequestDispatcher("/admin/menuTournoi.jsp").forward(
						request, response);

			}
			/**
			 * voirTournoi(id)
			 */
			else if (action.equals("voirTournoi")) {
				int id = Integer.parseInt(request.getParameter("id"));
				Tournoi t = facade.recupererTournoi(id);
				request.setAttribute("tournoi", t);
				request.getRequestDispatcher("/admin/voirTournoi.jsp").forward(
						request, response);

			}
			/**
			 * equipeTournoi(List<Equipe>)
			 */
			else if (action.equals("equipeTournoi")) {
				int id = Integer.parseInt(request.getParameter("id"));
				/* On récupére le tournoi */
				Tournoi t = facade.recupererTournoi(id);
				/* Si le tournoi n'est pas commencé */
				if (t.getEtat() == EtatTournoi.ATTENTE) {
					/* on récupére la liste des équipes déjà ajoutée */
					List<Equipe> le = (ArrayList<Equipe>) facade
							.recupererEquipes();
					request.setAttribute("equipes", le);
					request.setAttribute("tournoi", t);
					/* Si la liste n'est pas vide */
					if (t.getLesEquipes() != null
							&& !t.getLesEquipes().isEmpty()) {
						request.getRequestDispatcher(
								"/admin/equipeModifTournoi.jsp").forward(
								request, response);
					} else {
						request.getRequestDispatcher("/admin/equipeTournoi.jsp")
								.forward(request, response);
					}
				} else {
					request.setAttribute("etat",
							"<div class='alert alert-warning'><p>Tournoi déjà démarré !</p></div>");
					request.getRequestDispatcher("/admin/menuTournoi.jsp")
							.forward(request, response);
				}

			}
			/**
			 * modifierTournoi(id)
			 */
			else if (action.equals("modifierTournoi")) {
				int idTournoi = Integer.parseInt(request
						.getParameter("tournoi"));
				Tournoi t = facade.recupererTournoi(idTournoi);
				/* Si on peut encore modifier le tournoi */
				if (t.getEtat() == EtatTournoi.ATTENTE) {
					int nbEquipes = Integer.parseInt(request
							.getParameter("nbEquipe"));
					/*
					 * On fait un set pour avoir chaque équipe uniquement une
					 * fois
					 */
					Set<Integer> lesEquipes = new HashSet<Integer>();
					for (int i = 0; i < nbEquipes; i++) {
						String tmp = request.getParameter("Equipe" + i);
						if (!tmp.isEmpty())
							lesEquipes.add(Integer.parseInt(tmp));
					}

					/*
					 * On vérifie que la taille du set correspond à la taille
					 * attendu (pas de perte/duplication)
					 */
					if (lesEquipes.size() == nbEquipes) {
						List<Equipe> equipesTournoi = new ArrayList<Equipe>();
						/*
						 * on répère toute les équipes du set pour les ajouter
						 * au tournoi
						 */
						for (int i : lesEquipes) {
							Equipe e = facade.recupererEquipe(i);
							equipesTournoi.add(e);
						}
						t.setLesEquipes(equipesTournoi);
						facade.updateTournoi(t);
						request.setAttribute("tournoi", t);
						request.getRequestDispatcher("/admin/voirTournoi.jsp")
								.forward(request, response);
					} else {
						/* Sinon on retourne sur la page de saisie */
						List<Equipe> le = (ArrayList<Equipe>) facade
								.recupererEquipes();
						request.setAttribute("equipes", le);
						request.setAttribute("tournoi", t);
						request.setAttribute("etat",
								"<div class='alert alert-danger'><p>Erreur dans les équipes !</p></div>");
						/* On redirige vers le bon formulaire */
						if (t.getLesEquipes() != null
								&& !t.getLesEquipes().isEmpty()) {
							request.getRequestDispatcher(
									"/admin/equipeModifTournoi.jsp").forward(
									request, response);
						} else {
							request.getRequestDispatcher(
									"/admin/equipeTournoi.jsp").forward(
									request, response);
						}
					}
				} else {
					request.setAttribute("tournoi", t);
					request.getRequestDispatcher("/admin/voirTournoi.jsp")
							.forward(request, response);
				}

			}
			/**
			 * demarrerTournoi(id)
			 */
			else if (action.equals("demarrerTournoi")) {
				int idTournoi = Integer.parseInt(request
						.getParameter("tournoi"));
				Tournoi t = facade.recupererTournoi(idTournoi);
				t.demarrer();
				facade.updateTournoi(t);
				request.setAttribute("tournoi", t);
				request.setAttribute("etat",
						"<div class='alert alert-success'><p>Tournoi démarré !</p></div>");
				request.getRequestDispatcher("/admin/voirTournoi.jsp").forward(
						request, response);
			}
			/*
			 * =================================
			 * 
			 * MATCH
			 * 
			 * =================================
			 */
			else if (action.equals("assignerArbitre")) {
				int match = Integer.parseInt(request.getParameter("match"));
				List<Arbitre> la = (ArrayList<Arbitre>) facade
						.recupererArbitres();
				Rencontre r = facade.recupererMatch(match);
				request.setAttribute("match", r);
				request.setAttribute("arbitres", la);
				request.getRequestDispatcher("/admin/arbitreMatch.jsp")
						.forward(request, response);

			} else if (action.equals("ajouterArbitre")) {
				int match = Integer.parseInt(request.getParameter("match"));
				int arbitre = Integer.parseInt(request.getParameter("arbitre"));
				Arbitre a = facade.recupererArbitre(arbitre);
				Rencontre r = facade.recupererMatch(match);
				/* test si match a commencé (au moins un but) */
				if (!r.aDemarre()) {
					r.setArbitre(a);
					facade.updateMatch(r);
				} else {
					request.setAttribute(
							"etat",
							"<div class='alert alert-warning'><p>Impossible de changer l'arbitre une fois le match commencé !</p></div>");
				}
				request.setAttribute("match", r);
				request.getRequestDispatcher("/admin/modifierMatch.jsp")
						.forward(request, response);

			}
			/**
			 * modifierMatch(idTournoi,numPhase,idMatch)
			 */
			else if (action.equals("modifierMatch")) {
				int idTournoi = Integer.parseInt(request
						.getParameter("tournoi"));
				int phase = Integer.parseInt(request.getParameter("phase"));
				int match = Integer.parseInt(request.getParameter("match"));
				Tournoi t = facade.recupererTournoi(idTournoi);
				Colonne c = t.getPhases().get(phase);
				/* Si la colonne est apte à être modifiée */
				if (t.getEtat() == EtatTournoi.ENCOURS
						&& c.getEtat() == EtatColonne.ENCOURS) {
					/* modification du match */
					Rencontre r = c.getMatch(match);
					request.setAttribute("match", r);
					/* Si le match n'a pas encore d'arbitre on en assigne un */
					if (r.getArbitre() == null) {
						List<Arbitre> la = (ArrayList<Arbitre>) facade
								.recupererArbitres();
						request.setAttribute("arbitres", la);
						request.getRequestDispatcher("/admin/arbitreMatch.jsp")
								.forward(request, response);
					} else
						request.getRequestDispatcher("/admin/modifierMatch.jsp")
								.forward(request, response);
				} else {
					/* retour sur l'affichage du tournoi avec msg erreur */
					request.setAttribute("tournoi", t);
					request.setAttribute(
							"etat",
							"<div class='alert alert-danger'><p>Impossible de modifier cette rencontre !</p></div>");
					request.getRequestDispatcher("/admin/voirTournoi.jsp")
							.forward(request, response);
				}
			}
			/**
			 * infoMatch(id) : Avance l'état du match (normal/prol./TaB)
			 */
			else if (action.equals("infoMatch")) {
				int idMatch = Integer.parseInt(request.getParameter("match"));
				Rencontre r = facade.recupererMatch(idMatch);
				/* Avancer les infos */
				r.modifierInfo();
				facade.updateMatch(r);
				request.setAttribute("match", r);
				request.getRequestDispatcher("/admin/modifierMatch.jsp")
						.forward(request, response);

			}
			/**
			 * voirMatch(id)
			 */
			else if (action.equals("voirMatch")) {
				int idMatch = Integer.parseInt(request.getParameter("match"));
				/* récupérer le match */
				Rencontre r = facade.recupererMatch(idMatch);
				if (r.getEquipeUne() != null) {
					request.setAttribute("match", r);
					request.getRequestDispatcher("/admin/voirMatch.jsp")
							.forward(request, response);
				}
			}
			/**
			 * ajouterButMatch(idMatch,equipe,nom,minute)
			 */
			else if (action.equals("ajouterButMatch")) {

				int idMatch = Integer.parseInt(request.getParameter("match"));
				/* récupérer le match */
				Rencontre r = facade.recupererMatch(idMatch);
				String nom = request.getParameter("joueur");
				String sminute = request.getParameter("minute");

				int equipe = Integer.parseInt(request.getParameter("equipe"));
				try {
					if (sminute == null || sminute.isEmpty())
						throw new Exception("Minute vide !");
					int minute = Integer.parseInt(sminute);
					/* Ajouter un but */
					r.ajouterBut(equipe, nom, minute);
					/* Maj de la rencontre si réussite */
					facade.updateMatch(r);
					request.setAttribute("match", r);
				} catch (Exception e) {
					request.setAttribute("match", r);
					request.setAttribute(
							"etat",
							"<div class='alert alert-danger'><p>"
									+ e.getMessage() + "!</p></div>");
				}
				request.getRequestDispatcher("/admin/modifierMatch.jsp")
						.forward(request, response);
			}
			/**
			 * terminerMatch(id)
			 */
			else if (action.equals("terminerMatch")) {
				int idMatch = Integer.parseInt(request.getParameter("match"));
				Rencontre r = facade.recupererMatch(idMatch);
				try {
					r.finir();
					facade.updateMatch(r);
					/* MATCH TERMINE -> VERIFICATION DU TOURNOI */
					Tournoi t = facade.recupererTournoi(r.getTournoi());
					t.verifier();
					facade.updateTournoi(t);
					/* FIN VERIF */
					request.setAttribute("etat",
							"<div class='alert alert-success'><p>Rencontre terminée !</p></div>");
					request.setAttribute("match", r);
					request.getRequestDispatcher("/admin/voirMatch.jsp")
							.forward(request, response);
				} catch (Exception e) {
					request.setAttribute(
							"etat",
							"<div class='alert alert-danger'><p>"
									+ e.getMessage() + "!</p></div>");
					request.setAttribute("match", r);
					request.getRequestDispatcher("/admin/modifierMatch.jsp")
							.forward(request, response);
				}
			}
			/*
			 * =================================
			 * 
			 * EQUIPE
			 * 
			 * =================================
			 */
			else if (action.equals("ajoutEquipe")) {
				String nom = request.getParameter("nomEquipe");
				String joueur;

				List<String> lesJoueurs = new ArrayList<String>();
				// On met les joueurs dans une liste avec au moins 11 personnes
				for (int i = 0; i < 15; i++) {
					joueur = request.getParameter("Joueur" + i);
					if (!joueur.isEmpty())
						lesJoueurs.add(joueur);
				}
				if (nom == null || nom.isEmpty()) {
					request.setAttribute("lesJoueurs", lesJoueurs);
					request.setAttribute("nomEquipe", nom);
					request.setAttribute("etat",
							"<div class='alert alert-warning'><p>Nom vide !</p></div>");
				}
				// S'il y a moins de 11 personnes, on renvoit sur le formulaire
				else if (lesJoueurs.size() < 11) {
					request.setAttribute("lesJoueurs", lesJoueurs);
					request.setAttribute("nomEquipe", nom);
					request.setAttribute("etat",
							"<div class='alert alert-warning'><p>Pas assez de joueurs !</p></div>");
				}
				// Sinon on enregistre
				else {
					Equipe e = new Equipe();
					e.setNomEquipe(nom);
					e.setJoueurs(lesJoueurs);

					/*
					 * en fonction du résultat de l'ajout, différents messages à
					 * affiché
					 */
					if (facade.ajouterEquipe(e)) {
						request.setAttribute("etat",
								"<div class='alert alert-success'><p>Ajout effectué !</p></div>");
					} else
						request.setAttribute("etat",
								"<div class='alert alert-danger'>p>Erreur ajout ...</p></div>");
				}

				/* récupération des équipes pour l'affichage */
				ArrayList<Equipe> equipes = (ArrayList<Equipe>) facade
						.recupererEquipes();
				request.setAttribute("equipes", equipes);
				request.getRequestDispatcher("/admin/menuEquipe.jsp").forward(
						request, response);

			} else if (action.equals("supprimerEquipe")) {
				int numero = Integer.parseInt(request.getParameter("id"));
				facade.supprimerEquipe(numero);
				request.setAttribute("etat",
						"<div class='alert alert-warning'><p>Suppression effectuée !</p></div>");

				/* récupération des équipes pour l'affichage */
				ArrayList<Equipe> equipes = (ArrayList<Equipe>) facade
						.recupererEquipes();
				request.setAttribute("equipes", equipes);
				request.getRequestDispatcher("/admin/menuEquipe.jsp").forward(
						request, response);

			} else if (action.equals("voirEquipe")) {
				int id = Integer.parseInt(request.getParameter("id"));
				Equipe e = facade.recupererEquipe(id);
				request.setAttribute("equipe", e);
				request.getRequestDispatcher("/admin/voirEquipe.jsp").forward(
						request, response);

			}
			/*
			 * ===============================
			 * 
			 * ARBITRE
			 * 
			 * ===============================
			 */
			else if (action.equals("ajoutArbitre")) {
				String nom = request.getParameter("nomArbitre");

				Arbitre a = new Arbitre(nom);

				if (nom != null && !nom.isEmpty() && facade.ajouterArbitre(a)) {
					request.setAttribute("etat",
							"<div class='alert alert-success'><p>Ajout effectué !</p></div>");
				} else
					request.setAttribute("etat",
							"<div class='alert alert-danger'><p>Erreur ajout ...</p></div>");

				/* récupération des arbitres pour l'affichage */
				ArrayList<Arbitre> arbitres = (ArrayList<Arbitre>) facade
						.recupererArbitres();

				request.setAttribute("arbitres", arbitres);
				request.getRequestDispatcher("/admin/menuArbitre.jsp").forward(
						request, response);

			} else if (action.equals("supprimerArbitre")) {
				int numero = Integer.parseInt(request.getParameter("id"));
				facade.supprimerArbitre(numero);
				request.setAttribute("etat",
						"<div class='alert alert-warning'><p>Suppression effectuée !</p></div>");

				/* récupération des arbitres pour l'affichage */
				ArrayList<Arbitre> arbitres = (ArrayList<Arbitre>) facade
						.recupererArbitres();

				request.setAttribute("arbitres", arbitres);
				request.getRequestDispatcher("/admin/menuArbitre.jsp").forward(
						request, response);
			}
		}
	}
}
